package promotion

import (
	"fmt"
	"time"
	// "bp/cache"
	sqlc "bp/db/sqlc"
	"bp/db/sqlc/ctype"
	"bp/internal/util"
	"context"
)

// CreatePromotionParam 新建促销活动参数
type CreatePromotionParam struct {
	CreatePromotionParamsPtr *sqlc.CreatePromotionParams
}

// CreatePromotion 新建促销活动
func (s *PromotionEntityServiceImp) CreatePromotion(ctx context.Context, q *sqlc.Queries, ptr *CreatePromotionParam) (promotionPtr *sqlc.Promotion, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	promotion, err := q.CreatePromotion(ctx, *ptr.CreatePromotionParamsPtr)
	if err != nil {
		return
	}
	slog.Infof("1 CreatePromotion ok")

	promotionPtr = &promotion
	return
}

// UpdatePromotionParam 更新促销活动参数
type UpdatePromotionParam struct {
	PromotionID             int64
	Name                    string
	Desc                    string
	Tags                    []string
	OfferCategory           string
	OfferType               string
	Issuer                  string
	NeedVerifyQualification bool
	QualifyTypes            []string
	Price                   int32
	Quota                   int32
	OffMaximum              int32
	GradientRules           ctype.OffGradientRuleArray
	Begined                 time.Time
	Ended                   time.Time
	TimeRanges              ctype.TimeRangeArray
	DateChooseType          string
	Weekdays                []int32
	Monthdays               []int32
	UseScenes               []string
	Scope                   string
}

// UpdatePromotion 更新促销活动
func (s *PromotionEntityServiceImp) UpdatePromotion(ctx context.Context, q *sqlc.Queries, ptr *UpdatePromotionParam) (promotionPtr *sqlc.Promotion, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	promotionID := ptr.PromotionID
	promotionPtr, err = s.GetPromotionPtr(ctx, q, promotionID)
	if err != nil {
		return
	}
	slog.Infof("1 GetPromotionPtr ok")

	isAnyoneParticipated, err := q.CheckIsAnyoneParticipatedByPromotionID(ctx, promotionID)
	if err != nil {
		return
	}
	slog.Infof("2 CheckIsAnyoneParticipatedByPromotionID=>%v ok", isAnyoneParticipated)

	var promotion sqlc.Promotion
	if isAnyoneParticipated {

		// 思考?已发布到会员侧的券,修改品牌或商品必须增加
		promotion, err = q.UpdatePromotionWithParticipated(ctx, sqlc.UpdatePromotionWithParticipatedParams{
			ID:                      promotionID,
			Name:                    ptr.Name,
			Desc:                    sqlc.NSFromString(ptr.Desc),
			Tags:                    ptr.Tags,
			NeedVerifyQualification: ptr.NeedVerifyQualification,
			QualifyTypes:            ptr.QualifyTypes,
		})
	} else {
		promotion, err = q.UpdatePromotionWithoutParticipated(ctx, sqlc.UpdatePromotionWithoutParticipatedParams{
			ID:                      promotionID,
			Name:                    ptr.Name,
			Desc:                    sqlc.NSFromString(ptr.Desc),
			Tags:                    ptr.Tags,
			OfferCategory:           ptr.OfferCategory,
			OfferType:               ptr.OfferType,
			Issuer:                  ptr.Issuer,
			NeedVerifyQualification: ptr.NeedVerifyQualification,
			QualifyTypes:            ptr.QualifyTypes,
			Price:                   ptr.Price,
			Quota:                   ptr.Quota,
			OffMaximum:              ptr.OffMaximum,
			GradientRules:           ptr.GradientRules,
			Begined:                 ptr.Begined,
			Ended:                   ptr.Ended,
			TimeRanges:              ptr.TimeRanges,
			DateChooseType:          sqlc.NSFromString(ptr.DateChooseType),
			Weekdays:                ptr.Weekdays,
			Monthdays:               ptr.Monthdays,
			UseScenes:               ptr.UseScenes,
			Scope:                   ptr.Scope,
		})
	}
	if err != nil {
		return
	}
	slog.Infof("3 UpdatePromotion ok")

	promotionPtr = &promotion
	return
}

// UpdatePromotionStatusParam 更新促销活动状态参数
type UpdatePromotionStatusParam struct {
	PromotionPtr *sqlc.Promotion
	PromotionID  int64
}

// PublishPromotion 发布促销活动
func (s *PromotionEntityServiceImp) PublishPromotion(ctx context.Context, q *sqlc.Queries, ptr *UpdatePromotionStatusParam) (promotionPtr *sqlc.Promotion, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	if ptr.PromotionPtr != nil {
		promotionPtr = ptr.PromotionPtr
	} else {
		promotionPtr, err = s.GetPromotionPtr(ctx, q, ptr.PromotionID)
		if err != nil {
			return
		}
		slog.Infof("0 GetPromotionPtr ok")
	}
	if promotionPtr.PromotionStatus != string(sqlc.EmPromotionStatusDraft) {
		err = fmt.Errorf("促销活动状态不匹配")
		return
	}
	promotionID := promotionPtr.ID

	err = q.PublishPromotion(ctx, promotionID)
	if err != nil {
		return
	}
	promotionPtr.PromotionStatus = string(sqlc.EmPromotionStatusPublished)
	promotionPtr.Published = sqlc.NTimeFromTime(time.Now())
	slog.Infof("1 PublishPromotion ok")

	return
}

// PausePromotion 暂停促销活动
func (s *PromotionEntityServiceImp) PausePromotion(ctx context.Context, q *sqlc.Queries, ptr *UpdatePromotionStatusParam) (promotionPtr *sqlc.Promotion, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	if ptr.PromotionPtr != nil {
		promotionPtr = ptr.PromotionPtr
	} else {
		promotionPtr, err = s.GetPromotionPtr(ctx, q, ptr.PromotionID)
		if err != nil {
			return
		}
		slog.Infof("0 GetPromotionPtr ok")
	}
	if promotionPtr.PromotionStatus != string(sqlc.EmPromotionStatusPublished) {
		err = fmt.Errorf("促销活动状态不匹配")
		return
	}
	promotionID := promotionPtr.ID

	err = q.PausePromotion(ctx, promotionID)
	if err != nil {
		return
	}
	promotionPtr.PromotionStatus = string(sqlc.EmPromotionStatusPaused)
	promotionPtr.Paused = sqlc.NTimeFromTime(time.Now())
	slog.Infof("1 PausePromotion ok")

	return
}

// ResumePromotion 恢复促销活动
func (s *PromotionEntityServiceImp) ResumePromotion(ctx context.Context, q *sqlc.Queries, ptr *UpdatePromotionStatusParam) (promotionPtr *sqlc.Promotion, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	if ptr.PromotionPtr != nil {
		promotionPtr = ptr.PromotionPtr
	} else {
		promotionPtr, err = s.GetPromotionPtr(ctx, q, ptr.PromotionID)
		if err != nil {
			return
		}
		slog.Infof("0 GetPromotionPtr ok")
	}
	if promotionPtr.PromotionStatus != string(sqlc.EmPromotionStatusPaused) {
		err = fmt.Errorf("促销活动状态不匹配")
		return
	}
	promotionID := promotionPtr.ID

	err = q.ResumePromotion(ctx, promotionID)
	if err != nil {
		return
	}
	promotionPtr.PromotionStatus = string(sqlc.EmPromotionStatusPublished)
	promotionPtr.Resumed = sqlc.NTimeFromTime(time.Now())
	slog.Infof("1 ResumePromotion ok")

	return
}

// ExpirePromotions 过期促销活动
func (s *PromotionEntityServiceImp) ExpirePromotions(ctx context.Context, q *sqlc.Queries, limit int32) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	cnt, err := q.BatchFinishOrClosePromotion(ctx, limit)
	if err != nil {
		return
	}
	slog.Infof("BatchFinishOrClosePromotion (%d)条", cnt)

	return
}